# RTMP analyzer
# for analyzing files of RTMP traffic

import sys, os
from optparse import OptionParser
from collections import deque

from rtmp import *
from netutil import stringDump
from fo_client import RTMPStream, Packet, Header

# Command line arguments
parser = OptionParser('Usage: %prog [options] FILE')
parser.add_option("-f", "--first", type="int", dest="first", metavar="N",
                  help="show first N packets")
parser.add_option("-l", "--last", type="int", dest="last", metavar="N",
                  help="show last N packets")
parser.add_option("-v", "--verbose", dest="verbose", default=False,
                  action="store_true", help="show packet contents [default %default]")
(options, args) = parser.parse_args()

print options, args

if not len(args) == 1:
    parser.print_help()
    #sys.exit()
if options.last is not None and options.first is not None:
    parser.error('Cannot specify both FIRST and LAST options')
    #sys.exit()
if options.first is not None and options.first < 1:
    parser.error('FIRST must be positive')
if options.last is not None and options.last < 1:
    parser.error('LAST must be positive')

def format_header(packet):
    header = packet.header
    return "Packet(csid=%d, time=%6d, mtype=%-10s, sid=%d, len=%5d, hash=%x)" %\
           (header.csid, header.time, MTYPES.get(header.mtype, header.mtype),
            header.sid, len(packet.data), hash(packet.data))

def format_line(packet):
    line = format_header(packet)
    if options.verbose:
        line += '\n' + stringDump(packet.data)
    return line

with open(args[0], 'rb') as stream:
    rtmp = RTMPStream(stream)
    # skip handshake
    stream.read(1 + 1536 * 2)
    lineno = 0
    packets = deque()
    while stream.read(1):
        stream.seek(-1, os.SEEK_CUR)
        packet_start = stream.tell()
        lineno += 1
        try:
            packet = rtmp.read_chunk()
        except:
            if stream.read(1) == '':
                print 'error decoding packet: end of file reached'
                stream.seek(packet_start)
                err_packet = Packet(Header(-1, -1, -1, -1), stream.read(1000000))
                packets.append(err_packet)
                if options.last is not None and len(packets) > options.last:
                    packets.popleft()
            else:
                print 'error decoding packet: unknown error'
            break
        if options.first is not None:
            packets.append(packet)
            if lineno >= options.first:
                break
        elif options.last is not None:
            packets.append(packet)
            if len(packets) > options.last:
                packets.popleft()
        else:
            print line

    for packet in packets:
        print format_line(packet)
